<?php
/**
 * Smart Library - Smart Framework
 * http://smart-framework.highet.eu
 *
 * @category   SmartL
 * @package    SmartL_Zend
 * @subpackage Controller
 * @copyright  Copyright (c) 2005-2008 Smart Framework team - Stepan Sindelar, Vojtech Vit
 * @license    http://www.opensource.org/licenses/bsd-license.php	New BSD License
 */

/**
 * @see SmartL_Config
 */
require_once 'SmartL/Config.php';
/**
 * @see SmartL_Zend_Controller_Action_Config_ActionInfo
 */
require_once 'SmartL/Zend/Controller/Action/Config/ActionInfo.php';
/**
 * @see SmartL_Zend_Controller_Action_Config_ActionInfo_SelectionInfo
 */
require_once 'SmartL/Zend/Controller/Action/Config/ActionInfo/SelectionInfo.php';
/**
 * @see SmartL_Application
 */
require_once 'SmartL/Application.php';
/**
 * @see SmartL_Zend_View_Helper_Url
 */
require_once 'SmartL/Zend/View/Helper/Url.php';

/**
 *
 * @uses SmartL_Zend_Controller_Action_Config_ActionInfo
 * @uses SmartL_Zend_Controller_Action_Config_ActionInfo_SelectionInfo
 *
 * @package SmartL_Zend
 * @subpackage Controller
 *
 * @todo 16 done?: Podpora více typů joinu
 */
class SmartL_Zend_Controller_Action_Config extends SmartL_Config {
	private $actions = array ();
	
	/**
	 * Returns user access permissions for this controller.
	 *
	 * @return array Controller user access permissions
	 */
	public function getAccessPermissions() {
		if (isset ( $this->authorization ) and isset ( $this->authorization->allow )) {
			return $this->authorization->getChildValues ( "allow" );
		}
		return array ();
	}
	/**
	 * Returns user access restrictions for this controller.
	 *
	 * @return array Controller user access restrictions
	 */
	public function getAccessRestrictions() {
		if (isset ( $this->authorization ) and isset ( $this->authorization->deny )) {
			return $this->authorization->getChildValues ( "deny" );
		}
		return array ();
	}
	/**
	 * Returns whether this controller has specific configuration for given
	 * action.
	 *
	 * @param string $name Action name
	 * @return boolean True if action has some specific configuration
	 */
	public function hasActionConfig($name) {
		if ( !isset($this->action) ) return false;
		return isset ( $this->action [$name] );
	}
	/**
	 * Returns this controller's action info by it's name.
	 *
	 * @param string $name Action name
	 * @return SmartL_Zend_Controller_Action_Config_ActionInfo Action info
	 */
	public function getAction($name, $app = null) {
		if (isset ( $this->actions [$name] )) {
			return $this->actions [$name];
		}
		if ( isset( $this->action ) and isset ( $this->action [$name] )) {
			$data = $this->action [$name];
			$result = new SmartL_Zend_Controller_Action_Config_ActionInfo ( );
			
			// Load user access rules
			if (isset ( $data->authorization )) {
				// Permissions
				$allow = isset ( $data->authorization->allow ) ? $data->authorization->getChildValues ( "allow" ) : array ();
				$result->setAccessPermissions ( $allow );
				// Restrictions
				$deny = isset ( $data->authorization->deny ) ? $data->authorization->getChildValues ( "deny" ) : array ();
				$result->setAccessRestrictions ( $deny );
			}
			
			// Load translation file and adapter
			$this->_createActionTranslations ( $result, $data );
			
			//Load selections
			$this->_createActionSelections ( $result, $data );
			
			// Load forms
			$this->_createActionForms ( $result, $data, $app );
			
			// Load Cache info
			$this->_createCacheInfo ( $result, $data );
			
			$this->actions [$name] = $result;
			return $result;
		}
		require_once 'SmartL/Zend/Controller/Action/Config/Exception.php';
		throw new SmartL_Zend_Controller_Action_Config_Exception ( "Action with name {$name} doesn't exist." );
	}
	
	private function _createActionForms(SmartL_Zend_Controller_Action_Config_ActionInfo $action, SmartL_Config_Storage $actionNode, $app = null) {
		if (isset ( $actionNode->form )) {
			if ($app === null) {
				$app = SmartL_Application::getInstance ();
			}
			foreach ( $actionNode->form as $name => $data ) {
				$forms [$name] = $data->toArray ();
				if (isset ( $forms [$name] ['action'] )) {
					if (is_array ( $forms [$name] ['action'] )) {
						$url = new SmartL_Zend_View_Helper_Url ( );
						$forms [$name] ['action'] = $url->url ( $forms [$name] ['action'] );
					} else if ($app->getBaseUrl () != "") {
						$forms [$name] ['action'] = '/' . $app->getBaseUrl () . '/' . $forms [$name] ['action'];
					} else {
						$forms [$name] ['action'] = "/" . $forms [$name] ['action'];
					}
				} else {
					$url = new SmartL_Zend_View_Helper_Url ( );
					$forms [$name] ['action'] = $url->url (array(), null, false);
				}
			}
			$action->setForms ( $forms );
		}
	}
	
	private function _createActionTranslations(SmartL_Zend_Controller_Action_Config_ActionInfo $action, SmartL_Config_Storage $actionNode) {
		if (! isset ( $actionNode->translations ))
			return;
		$data = $actionNode->translations;
		
		if (isset ( $data->autoload ) and strtolower ( $data->autoload->getValue () ) == "true") {
			$defaultFile = new SmartL_Zend_Controller_Action_Config_ActionInfo_TranslationInfo ( );
			$defaultFile->setAdapter ( $data->adapter->getValue () );
			$defaultFile->setId ( "default" );
			if (isset ( $data->autoload->extension ))
				$defaultFile->setExtension ( $data->autoload->extension->getValue () );
			if (isset ( $data->autoload->file ))
				$defaultFile->setFile ( $data->autoload->file->getValue () );
			$result ["default"] = $defaultFile;
		}
		
		if (isset ( $data->loadedFiles )) {
			foreach ( $data->loadedFiles as $id => $fileData ) {
				if ($id == "default") {
					require_once 'SmartL/Zend/Controller/Action/Config/Exception.php';
					throw new SmartL_Zend_Controller_Action_Config_Exception ( "No translation could have id 'default'" );
				}
				$newFile = new SmartL_Zend_Controller_Action_Config_ActionInfo_TranslationInfo ( );
				$newFile->setId ( $id );				
				$newFile->setAdapter ( $fileData->adapter->getValue () );
				$newFile->setFile ( $fileData->file->getValue () );
				if (isset ( $fileData->extension ))
					$newFile->setExtension ( $fileData->extension->getValue () );
				$result [$id] = $newFile;
			}
		}
		
		if (isset ( $result )) {
			$action->setTranslations ( $result );
		}
	}
	
	private function _createActionSelections(SmartL_Zend_Controller_Action_Config_ActionInfo $action, SmartL_Config_Storage $actionNode) {
		$data = $actionNode;
		if (isset ( $data->selection )) {
			foreach ( $data->selection as $name => $selData ) {
				$selection = new SmartL_Zend_Controller_Action_Config_ActionInfo_SelectionInfo ( );
				if (isset ( $selData->columns )) {
					foreach ( $selData->columns as $column => $trash ) {
						$columns [] = $column;
					}
					$selection->setColumns ( $columns );
				}
				if (!empty ( $selData->joinTables )) {
					foreach ( $selData->joinTables as $table => $tableData ) {
						$tables [$tableData->type->getValue ()] [] = $table;
					}
					$selection->setJoinTables ( $tables );
				}
				$action->addSelection ( $name, $selection );
			}
		}
	}
	
	private function _createCacheInfo(SmartL_Zend_Controller_Action_Config_ActionInfo $action, SmartL_Config_Storage $actionNode) {
		//Does this action have cache configuration
		if (isset ( $actionNode->cache )) {
			$actionNode = $actionNode->cache;
			$inArray = $actionNode->toArray(false);
			
			//Adapter, disabled, spefificLifetime
			$adapter = isset ( $actionNode->specificCacheAdapterName ) ? $actionNode->specificCacheAdapterName->getValue () : null;
			$disabled = isset ( $actionNode->disabled ) ? $actionNode->disabled->getBooleanValue () : false;
			$specificLifetime = isset ( $actionNode->specificLifetime ) ? $actionNode->specificLifetime->getValue () : null;
			
			//IdRules
			if (isset ( $actionNode->cacheIdRules )) {
				$cacheIdRules = $inArray['cacheIdRules'];
			}
			$cacheIdRulesndexes = array ("useParams", "useLanguageId", "useUserId", "notcacheWhenUserLogged" );
			foreach ( $cacheIdRulesndexes as $index ) {
				if (! isset ( $cacheIdRules [$index] )) {
					$cacheIdRules [$index] = true;
				} else {
					$cacheIdRules [$index] = strtolower ( $cacheIdRules [$index] ) == 'true';
				}
			}
			
			//Cache tags
			$cacheTags = array();
			if ( isset($actionNode->cacheTags) ) {
				$cacheTags = array_keys($inArray['cacheTags']);
			}
			
			$action->setCacheInfo ( new SmartL_Zend_Controller_Action_Config_ActionInfo_CacheInfo ( $adapter, $disabled, $specificLifetime, $cacheIdRules, $cacheTags ) );
		}
	}
}